#pragma once
/***********************************************************************************************
COPYRIGHT 2011 Mafahir Fairoze

This file is part of Neural++.
(Project Website : http://mafahir.wordpress.com/projects/neuralplusplus)

Neural++ is a free software. You can redistribute it and/or modify it under the terms of
the GNU General Public License as published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.

Neural++ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License <http://www.gnu.org/licenses/> for more details.

***********************************************************************************************/


#include "ConnectionMode.h"
#include "INeuron.h"
#include "IInitializer.h"
#include "Layer.h"
#include "ISynapse.h"

namespace NeuralPlusPlus
	{
	namespace Core        
		{
		class IInitializer;
		class Layer;
		class ISynapse;
		class INeuron;

		/// <summary>
		/// A connector represents a collection of synapses connecting two layers in a network.
		/// </summary>
		class Connector abstract
			{
			/// <summary>
			/// The source layer. It is initialized in constructor and is never changed later. It is
			/// never <c>NULL</c>.
			/// </summary>
			public: Layer *SourceLayer;

					   /// <summary>
					   /// The target layer. It is initialized in constructor and is never changed later. It is
					   /// never <c>NULL</c>.
					   /// </summary>
			public: Layer *TargetLayer;

					   /// <summary>
					   /// Array of synapses in the connector. It is never <c>NULL</c>.
					   /// </summary>
			public: ISynapse **Synapses;
			public: int SynapsesLength;

					   /// <summary>
					   /// The mode of connection (One-one or Complete). It is initialized in the constructor and
					   /// is immutable.
					   /// </summary>
			public: ConnectionModeType ConnectionMode;

					   /// <summary>
					   /// Initializer used to initialize the connector
					   /// </summary>
			public: IInitializer *Initializer;

					/// <summary>
					/// Creates a new connector between given layers using the connection mode specified.
					/// </summary>
			protected: Connector(Layer *sourceLayer, Layer *targetLayer, ConnectionModeType connectionMode);

					/// <summary>
					/// Adds small random noise to weights of synapses so that the network deviates from its
					/// local optimum position (a local equilibrium state where further learning is of no use)
					/// </summary>
			public: void Jitter(double jitterNoiseLimit);

					/// <summary>
					/// Gets a enumerator to a collection of source synapses of the neuron which belong to this->
					/// connector
					/// </summary>
			public: std::vector<ISynapse*>* GetSourceSynapses(INeuron *neuron);

					/// <summary>
					/// Gets a enumerator to a collection of target synapses of the neuron which belong to this->
					/// connector
					/// </summary>
			public: std::vector<ISynapse*>* GetTargetSynapses(INeuron *neuron);

					/// <summary>
					/// Initializes all synapses in the connector and makes them ready to undergo training
					/// freshly. (Adjusts the weights of synapses using the initializer)
					/// </summary>
			public: virtual void Initialize() = 0;

					/// <summary>
					/// Private helper to construct synapses between layers
					/// </summary>
			protected: virtual void ConstructSynapses() = 0;

					/// <summary>
					/// Deallocates memory
					/// </summary>
			public: ~Connector();
			};
		}    
	}